home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgramD2.iso / Borland / Borland C++ V5.02 / OWLSRC.PAK / WSKSERVM.CPP < prev    next >
C/C++ Source or Header  |  1997-05-06  |  12KB  |  319 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectWindows
  3. // Copyright (c) 1995, 1997 by Borland International, All Rights Reserved
  4. //
  5. //$Revision:   10.12  $
  6. //
  7. // Winsock for OWL subsystem.
  8. // Based on work by Paul Pedriana, 70541.3223@compuserve.com
  9. //----------------------------------------------------------------------------
  10. #include <owl/pch.h>
  11. #if !defined(OWL_WINSOCK_H)
  12. # include <owl/winsock.h>
  13. #endif
  14.  
  15. OWL_DIAGINFO;
  16.  
  17. //
  18. //
  19. //
  20. DEFINE_RESPONSE_TABLE1(TServiceWindow, TWindow)
  21.    EV_MESSAGE(MSG_SERVICE_NOTIFY, DoNotification),
  22. END_RESPONSE_TABLE;
  23.  
  24. //
  25. // A TServiceWindow requires a TServiceManager parent.
  26. //
  27. TServiceWindow::TServiceWindow(TServiceManager* serviceManagerParent)
  28. :
  29.   TWindow(0, "WinsockServiceWindow"),
  30.   ServiceManagerParent(serviceManagerParent)
  31. {
  32.   Attr.Style = 0;  // Turn off WS_CHILD (the default) style).
  33. }
  34.  
  35. //
  36. // This function merely calls the parent notification function.  Since Windows is designed
  37. //  to only allow Windows to receive system messages, we use a dummy window that does nothing
  38. //  but simulate the concept of Objects receiveing messages, in this case, the ServceManager
  39. //  object.  The TServiceWindow hides this from the user (programmer).
  40. //
  41. TResult TServiceWindow::DoNotification(TParam1, TParam2 param2)
  42. {
  43.   ServiceManagerParent->ServiceCompleted(WSAGETASYNCERROR(param2));
  44.   return 1;
  45. }
  46.  
  47. //----------------------------------------------------------------------------
  48.  
  49. //
  50. // Initialize all data members of servent to 0.
  51. //
  52. TServiceEntry::TServiceEntry()
  53. {
  54.   s_name    = 0;
  55.   s_aliases = 0;
  56.   s_port    = 0;
  57.   s_proto   = 0;
  58. }
  59.  
  60. //----------------------------------------------------------------------------
  61.  
  62. //
  63. // Create the hidden window and initialize data members.
  64. //
  65. TServiceManager::TServiceManager()
  66. :
  67.   Window(this)
  68. {
  69.   ServiceEntry = (TServiceEntry*)&ServiceBuffer;
  70.   LastServiceRequest          = 0;
  71.   LastError                   = 0;
  72.   LastServiceRequestCompleted = 0;
  73.   OutstandingServiceRequests  = 0;
  74.   try {
  75.     Window.Create();
  76.   }
  77.   catch (...) {
  78.     //Invalid Window exception.
  79.   }
  80. }
  81.  
  82. //
  83. // Perform cleanup by cancelling any outstanding service requests.
  84. //
  85. TServiceManager::~TServiceManager()
  86. {
  87.   // If there is an outstanding request...
  88.   //
  89.   if (LastServiceRequest && !LastServiceRequestCompleted)
  90.     CancelServiceRequest();
  91. }
  92.  
  93. //
  94. // Implements the blocking 'getservbyport()'.
  95. //
  96. // 'entry' is a pointer to a ServiceEntry*. The caller does NOT allocate a
  97. //  ServiceEntry, it will be set by the system.  DO NOT chanage any data in the
  98. //  returned structure.
  99. // 'port' is passed to this function in network byte ordering.
  100. // 'protocol' is the protocol name, but may be passed as 0 to mean default or first found.
  101. // The returned entry has the port in network byte order.
  102. //
  103. int TServiceManager::GetService(TServiceEntry*& entry, ushort port, const char* protocol)
  104. {
  105.   entry = (TServiceEntry*)TWinSockDll::getservbyport(port, protocol);
  106.   if (!entry) {
  107.     LastError = TWinSockDll::WSAGetLastError();
  108.     return WINSOCK_ERROR;
  109.   }
  110.   return WINSOCK_NOERROR;
  111. }
  112.  
  113. //
  114. // Implements the blocking 'getservbyname()'.
  115. //
  116. // 'entry' is a pointer to a ServiceEntry*. The caller does NOT allocate a
  117. //  ServiceEntry, it will be set by the system.  DO NOT chanage any data in the
  118. //  returned structure.
  119. // The 'name' argument points to string representing the service name, such as
  120. //  "ftp". It is generally case sensitive.
  121. // 'protocol' is the protocol name, but may be passed as 0 to mean default or
  122. //  first found.
  123. // The returned entry has the port in network byte order.
  124. //
  125. int TServiceManager::GetService(TServiceEntry*& entry, const char* name, const char* protocol)
  126. {
  127.   entry = (TServiceEntry*)TWinSockDll::getservbyname(name, protocol);
  128.   if (!entry) {
  129.     LastError = TWinSockDll::WSAGetLastError();
  130.     return WINSOCK_ERROR;
  131.   }
  132.   return WINSOCK_NOERROR;
  133. }
  134.  
  135. //
  136. // This function is blocking.
  137. // Given an input service in 'name', this function fills in nPort with the
  138. //  port (in network order).
  139. // 'port' is a reference to an int.  If the call retuns OK, then this will be the port
  140. //  in network ordering.
  141. // protocol is the protocol name, but may be passed as 0 to mean default or first found.
  142. //
  143. int TServiceManager::GetServicePort(char* name, ushort& port, const char* protocol)
  144. {
  145.   TServiceEntry* tempServiceEntry;
  146.  
  147.   int returnValue = GetService(tempServiceEntry, name, protocol);
  148.   port = tempServiceEntry->s_port; // Note that port is already in host byte order.
  149.   return returnValue;
  150. }
  151.  
  152. //
  153. // This function is blocking.
  154. // 'name' needs to be big enough to hold the service's name (N_MAX_SERVICE_NAME).
  155. // 'port' must be passed in network byte ordering.
  156. // 'protocol' is the protocol name, but may be passed as 0 to mean default or first found.
  157. //
  158. int TServiceManager::GetServiceName(ushort port, char* name, const char* protocol)
  159. {
  160.   // Note that because we are calling our own member function, we don't convert
  161.   //  the address from local to network format.
  162.   //
  163.   TServiceEntry* tempServiceEntry;
  164.   int returnValue = GetService(tempServiceEntry, port, protocol);
  165.   if (returnValue == WINSOCK_NOERROR)
  166.     strcpy(name, tempServiceEntry->s_name);
  167.   return returnValue;
  168. }
  169.  
  170. //
  171. // Cancels an pending service that equals the hService.  Note that if service
  172. // is 0 or unspecified, then this function uses its own current Service.
  173. //
  174. int TServiceManager::CancelServiceRequest(HANDLE hService)
  175. {
  176.   if (!hService)
  177.     hService = LastServiceRequest;
  178.   if (!hService) {
  179.     LastError = WSAEINVAL;
  180.     return WINSOCK_ERROR;
  181.   }
  182.  
  183.   int tempValue = TWinSockDll::WSACancelAsyncRequest(hService);
  184.   if (tempValue == SOCKET_ERROR) {
  185.     LastError = TWinSockDll::WSAGetLastError();
  186.     return WINSOCK_ERROR;
  187.   }
  188.   OutstandingServiceRequests--;
  189.   return WINSOCK_NOERROR;
  190. }
  191.  
  192. //
  193. // This call is non-blocking.  It sets up a callback to its own member window.
  194. // hService is a HANDLE reference.  If the call is successful, it will hold the handle for
  195. //  the asynchrous call.  Note that the caller can save the handle, but also that this
  196. //  class stores the handle for itself as well.
  197. // port is passed into this function in network byte ordering.
  198. // Note that due to the design of this class, you cannot have two outstanding Service
  199. //  requests that get notified directly to this class.  You may use the hwnd-specific
  200. //  notification version of this function to manage multiple requests at a time.
  201. //  You may also simply create more than one instance of this class.
  202. // The service is complete when bServiceRequestCompleted is TRUE.  You must look at nLastError in
  203. //  this case to see if there was an error.
  204. //
  205. int TServiceManager::GetServiceAsync(HANDLE& hService, ushort port, const char* protocol)
  206. {
  207.   LastServiceRequestCompleted = 0;
  208.   hService = LastServiceRequest = TWinSockDll::WSAAsyncGetServByPort(Window, MSG_SERVICE_NOTIFY,
  209.                                          port, protocol, ServiceBuffer, MAXGETHOSTSTRUCT);
  210.   if (!hService) {
  211.     LastError = TWinSockDll::WSAGetLastError();
  212.     return WINSOCK_ERROR;
  213.   }
  214.  
  215.   OutstandingServiceRequests++;
  216.   return WINSOCK_NOERROR;
  217. }
  218.  
  219. //
  220. // This call is non-blocking.  It sets up a callback to its own member window.
  221. // 'hService' is a HANDLE reference.  If the call is successful, it will hold the handle for
  222. //  the asynchrous call.  Note that the caller can save the handle, but also that this
  223. //  class stores the handle for itself as well.
  224. // The 'name' argument points to a service name, such as "finger".
  225. // protocol is the protocol name, but may be passed as 0 or not passed at all to mean
  226. //  default or first found.
  227. //
  228. int TServiceManager::GetServiceAsync(HANDLE& hService, char* name, const char* protocol)
  229. {
  230.   LastServiceRequestCompleted=0;
  231.   hService = LastServiceRequest = TWinSockDll::WSAAsyncGetServByName(Window, MSG_SERVICE_NOTIFY,
  232.                                     name, protocol, ServiceBuffer, MAXGETHOSTSTRUCT);
  233.   if (!hService) {
  234.     LastError = TWinSockDll::WSAGetLastError();
  235.     return WINSOCK_ERROR;
  236.   }
  237.   OutstandingServiceRequests++;
  238.   return WINSOCK_NOERROR;
  239. }
  240.  
  241. //
  242. // This function notifies the given wndNotify about the completion of the request.
  243. // nMessage is the message that the hwndNotify will receive. It defaults to MSG_SERVICE_NOTIFY,
  244. //  which is defined in the TServiceManager's header file.
  245. // The hService will hold a handle that the caller can use to reference the request on call-back.
  246. // port should be passed in network byte ordering.
  247. // The chBuffer is a pointer to buffer that will be filled in with a SERVENT.  Needs to be at least
  248. //  MAXGETHOSTSTRUCT bytes.  If chBuffer is 0 (or not specified), then the TServiceManager's
  249. //  internal buffer will be used.
  250. // protocol is the protocol name, but may be passed as 0 to mean default or first found.
  251. // This class will NOT save the hServcice for itself.
  252. //   wParam will be equal to the hService returned.
  253. //   WSAGETSYNCERROR(lParam)   holds an error, if any (0 is OK).
  254. //   WSAGETSYNCBUFLEN(lParam)  hold actual length of buffer
  255. //
  256. int TServiceManager::GetServiceAsync(TWindow& wndNotify, HANDLE& hService,
  257.                                      ushort port, const char* protocol,
  258.                                      uint message, char* buffer)
  259. {
  260.   char* bufferToUse = buffer ? buffer : ServiceBuffer;
  261.  
  262.   LastServiceRequestCompleted=0;
  263.   hService = TWinSockDll::WSAAsyncGetServByPort(wndNotify, message, port,
  264.                                     protocol, bufferToUse, MAXGETHOSTSTRUCT);
  265.   if (!hService) {
  266.     LastError = TWinSockDll::WSAGetLastError();
  267.     return WINSOCK_ERROR;
  268.   }
  269.   return WINSOCK_NOERROR;
  270. }
  271.  
  272. //
  273. // This function notifies the given wndNotify about the completion of the request.
  274. // nMessage is the message that the hwndNotify will receive. It defaults to MSG_SERVICE_NOTIFY,
  275. //  which is defined in the TServiceManager's header file.
  276. // The hService will hold a handle that the caller can use to reference the request on call-back.
  277. // The chBuffer is a pointer to buffer that will be filled in with a SERVENT.  Needs to be at least
  278. //  MAXGETHOSTSTRUCT bytes.  If chBuffer is 0 (or not specified), then the TServiceManager's
  279. //  internal buffer will be used.
  280. // 'name' is a pointer to a c string service name, such as "ftp".
  281. // 'protocol' is the protocol name, but may be passed as 0 to mean default or first found.
  282. //
  283. // This class will NOT save the 'hService' for itself.
  284. //   wParam will be equal to the hService returned.
  285. //   WSAGETSYNCERROR(lParam)   holds an error, if any (0 is OK).
  286. //   WSAGETSYNCBUFLEN(lParam)  hold actual length of buffer
  287. //
  288. int TServiceManager::GetServiceAsync(TWindow& wndNotify, HANDLE& hService,
  289.                                      char* name, const char* protocol,
  290.                                      uint message, char* buffer)
  291. {
  292.   char* bufferToUse = buffer ? buffer : ServiceBuffer;
  293.  
  294.   LastServiceRequestCompleted = 0;
  295.   hService = TWinSockDll::WSAAsyncGetServByName(wndNotify, message, name,
  296.                                      protocol, bufferToUse, MAXGETHOSTSTRUCT);
  297.   if (!hService) {
  298.     LastError = TWinSockDll::WSAGetLastError();
  299.     return WINSOCK_ERROR;
  300.   }
  301.   return WINSOCK_NOERROR;
  302. }
  303.  
  304. //
  305. // This function is called whenever an internal window callback is used for an
  306. //  async call.  When this function is called, the ServiceRequestCompleted member
  307. //  will be true (it got set to true right before this function was called).
  308. //
  309. // You may want to override this function. If you do, you will probably want to
  310. // call this function as part of the subclassed function.
  311. //
  312. void TServiceManager::ServiceCompleted(int error)
  313. {
  314.   if (error == SOCKET_ERROR)
  315.     LastError = error;
  316.   OutstandingServiceRequests--;
  317.   LastServiceRequestCompleted = 1;
  318. }
  319.